package edu.maping.easy.editor;

import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import processing.core.PApplet;
import edu.maping.easy.gui.ScreenLogger;
import edu.maping.easy.model.Point;
import edu.maping.easy.model.PolygonThing;
import edu.maping.easy.model.PolygonThingBezier;
import edu.maping.easy.model.Thing;
import edu.maping.easy.model.World;

/**
 * Encapsula la lógica de edición de polígonos TODO dividir en DOS, selector y
 * move
 * 
 * @author MISTHAK47
 * 
 */

public class EditManager {

	public Thing newThing;
	public Thing moveThing;
	public ScreenLogger screenLogger;
	public List<Thing> selectedThings = new ArrayList<Thing>();
	boolean newPolygon = false;

	boolean multipleSelectMove = false;

	Point startMultipleEditPoint = null;
	Point endMultipleEditPoint = null;

	Point editingVertexPolygon = null;
	Point editVertexStart = new Point(0, 0);
	Point editThingStart = new Point(0, 0);

	public void mouseClicked(int mouseX, int mouseY, MouseEvent mouseEvent,
			World world, PolygonFactory polygonFactory) {

		// NEW POINT TO POLYGON
		if (newThing != null && newThing instanceof PolygonThing
				&& mouseEvent.getButton() == MouseEvent.BUTTON1) {
			PolygonThing polyThing = (PolygonThing) newThing;
			polyThing.addPoint(new Point(mouseX, mouseY));
		}

		if (newThing == null) {

			if (mouseEvent.getButton() == MouseEvent.BUTTON1) {
				PolygonThing hover = world.hovered(mouseX, mouseY);
				if (hover != null) {
					this.newThing = hover;
					selectedThings.add(newThing);
					screenLogger.writeText("Polygon Selected");
				}
			}
			// NEW POLYGON
			if (mouseEvent.getButton() == MouseEvent.BUTTON3) {
				startPolygon(polygonFactory);
			}
		} else {
			if (mouseEvent.getButton() == MouseEvent.BUTTON3) {
				// END POLYGON
				endPolygon(world);
			}
		}
	}

	private void setXYPoint(int x, int y, Point point) {
		point.setXY(x, y);
//		if (newThing != null) {
//			newThing.refresh();
//		}
	}

	public void mousePreassed(int mouseX, int mouseY, World world) {

		if (newThing != null && newThing instanceof PolygonThing) {

			PolygonThing physicPolyThing = (PolygonThing) newThing;

			Point vertexSelected = physicPolyThing.getPoint(mouseX, mouseY);

			if (vertexSelected != null) {
				editingVertexPolygon = vertexSelected;
				setXYPoint(mouseX, mouseY, editVertexStart);
			} else {

			}
			return;
		}

		PolygonThing thing = world.hovered(mouseX, mouseY);
		// MOVEMENT
		if (thing != null) {
			setXYPoint(mouseX, mouseY,editThingStart);
			// MOVE ONE THInG OR MULTIPLE
			if (selectedThings.isEmpty() || !selectedThings.contains(thing)) {
				moveThing = thing;
			} else {
				multipleSelectMove = true;
			}
		}
		// SELECTION
		if (!selectedThings.isEmpty() && selectedThings.contains(thing)) {

		} else {// if (thing != null) {
			setXYPoint(mouseX, mouseY,editThingStart);
			return;
		}
	}

	public void mouseDragged(int mouseX, int mouseY) {

		if (editingVertexPolygon != null) {
			int difX = mouseX - editVertexStart.getX();
			int difY = mouseY - editVertexStart.getY();
			editingVertexPolygon.move(difX, difY);
			setXYPoint(mouseX, mouseY,editVertexStart);
		}

		if (!multipleSelectMove && moveThing != null) {
			int difX = mouseX - editThingStart.getX();
			int difY = mouseY - editThingStart.getY();
			moveThing.moveXY(difX, difY);
			setXYPoint(mouseX, mouseY,editThingStart);
		}

		if (multipleSelectMove) {
			int difX = mouseX - editThingStart.getX();
			int difY = mouseY - editThingStart.getY();

			for (int index = 0; index < selectedThings.size(); index++) {
				Thing movingThing = selectedThings.get(index);
				movingThing.moveXY(difX, difY);
			}
			setXYPoint(mouseX, mouseY,editThingStart);
		}

		if (!multipleSelectMove)
			endMultipleEditPoint = new Point(mouseX, mouseY);
	}

	public void mouseReleased(int mouseX, int mouseY, World world) {

		if (editingVertexPolygon != null) {
			int difX = mouseX - editVertexStart.getX();
			int difY = mouseY - editVertexStart.getY();

			editingVertexPolygon.move(difX, difY);
			editingVertexPolygon = null;

			setXYPoint(0, 0,editVertexStart);
		}

		// else
		if (moveThing != null) {
			int difX = mouseX - editThingStart.getX();
			int difY = mouseY - editThingStart.getY();
			moveThing.moveXY(difX, difY);
			setXYPoint(0, 0,editThingStart);
			moveThing.refresh();
			moveThing = null;
		}

		if (startMultipleEditPoint != null && endMultipleEditPoint != null
				&& !multipleSelectMove) {
			List<Thing> thingsSelected = world.findByRectangle(
					startMultipleEditPoint, endMultipleEditPoint);
			selectedThings.clear();
			if (!thingsSelected.isEmpty()) {
				selectedThings.addAll(thingsSelected);
			}
		}

		if (newThing != null && newThing instanceof PolygonThing) {
			PolygonThing physicPolyThing = (PolygonThing) newThing;
			physicPolyThing.refresh();
		}

		multipleSelectMove = false;
		startMultipleEditPoint = null;
		endMultipleEditPoint = null;
	}

	private void startPolygon(PolygonFactory polygonFactory) {

		// newThing = new PolygonThing(0, 0);
		newThing = polygonFactory.getNewPolygon();
		newPolygon = true;
		screenLogger
				.writeText("New Polygon Started, click to add vertex, right another for end.");
	}

	private void endPolygon(World world) {

		screenLogger.writeText("New Polygon Finished");
		if (newThing != null && newThing instanceof PolygonThing) {
			PolygonThing polyThing = (PolygonThing) newThing;
			if (!polyThing.vertex.isEmpty()) {
				world.world.add(newThing);
			}
		}
		newPolygon = false;
		newThing = null;
	}
}
